﻿using System;
using System.Configuration;
using System.Configuration.Provider;
using System.Linq;
using System.Web.Security;

namespace Alogient.Cameleon.Membership
{
    public sealed class CMRoleProvider : RoleProvider
    {
        public override string ApplicationName { get; set; }

        public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
        {
            // Initialize values from web.config.
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }

            if (string.IsNullOrEmpty(name))
            {
                name = "CMRoleProvider";
            }

            // Initialize the abstract base class.
            base.Initialize(name, config);

            this.ApplicationName = GetConfigValue(config["applicationName"], "/");

            // Connection String
            ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings[config["connectionStringName"]];

            if (connectionStringSettings == null || string.IsNullOrWhiteSpace(connectionStringSettings.ConnectionString))
            {
                throw new ProviderException("Connection string cannot be blank.");
            }

            Utils.ConfigurationUtils.ConnectionString = connectionStringSettings.ConnectionString;
        }

        /// <summary>
        /// A helper function to retrieve config values from the configuration file. 
        /// </summary>
        /// <param name="configValue">Config Value</param>
        /// <param name="defaultValue">Default Value</param>
        /// <returns>Config value</returns>
        private static string GetConfigValue(string configValue, string defaultValue)
        {
            if (String.IsNullOrEmpty(configValue))
            {
                return defaultValue;
            }

            return configValue;
        }
        
        public override void AddUsersToRoles(string[] userNames, string[] roleNames)
        {
            // Validating Roles
            if (roleNames.Any(rolename => !this.RoleExists(rolename)))
            {
                throw new ProviderException("Role name not found.");
            }

            // Validating Users and Users in roles
            foreach (var username in userNames)
            {
                if (username.Contains(","))
                {
                    throw new ArgumentException("User names cannot contain commas.");
                }

                string username1 = username;
                if (roleNames.Any(rolename => this.IsUserInRole(username1, rolename)))
                {
                    throw new ProviderException("User is already in role.");
                }
            }

            // Adding Roles To Users
            foreach (var username in userNames)
            {
                foreach (var rolename in roleNames)
                {
                    throw new NotImplementedException("Not implemented"); // TODO
                }
            }
        }

        public override void CreateRole(string roleName)
        {
            if (roleName.Contains(","))
            {
                throw new ArgumentException("Role names cannot contain commas.");
            }

            if (this.RoleExists(roleName))
            {
                throw new ProviderException("Role name already exists.");
            }

            throw new NotImplementedException("Not implemented"); // TODO
        }

        public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
        {
            if (!this.RoleExists(roleName))
            {
                throw new ProviderException("Role does not exist.");
            }

            if (throwOnPopulatedRole && this.GetUsersInRole(roleName).Length > 0)
            {
                throw new ProviderException("Cannot delete a populated role.");
            }

            throw new NotImplementedException("Not implemented"); // TODO
        }

        public override string[] FindUsersInRole(string roleName, string usernameToMatch)
        {
            throw new NotImplementedException("Not implemented"); // TODO
        }

        public override string[] GetAllRoles()
        {
            throw new NotImplementedException("Not implemented"); // TODO
        }
        
        public override string[] GetRolesForUser(string username)
        {
            throw new NotImplementedException("Not implemented"); // TODO
        }

        public override string[] GetUsersInRole(string roleName)
        {
            throw new NotImplementedException("Not implemented"); // TODO
        }

        public override bool IsUserInRole(string username, string roleName)
        {
            throw new NotImplementedException("Not implemented"); // TODO
        }

        public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
        {
            // Validate Roles
            if (roleNames.Any(rolename => !this.RoleExists(rolename)))
            {
                throw new ProviderException("Role name not found.");
            }

            // Validate Users
            if ((from username in usernames
                 from rolename in roleNames
                 where !this.IsUserInRole(username, rolename)
                 select username).Any())
            {
                throw new ProviderException("User is not in role.");
            }

            foreach (var username in usernames)
            {
                foreach (var rolename in roleNames)
                {
                    throw new NotImplementedException("Not implemented"); // TODO
                }
            }
        }

        public override bool RoleExists(string roleName)
        {
            throw new NotImplementedException("Not implemented"); // TODO
        }
    }
}
